package org.liaohailong.library.crash;


import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.os.Build;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.NonNull;

import org.liaohailong.library.log.Logcat;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * 全局捕获闪退控制类
 *
 * @author wujianning
 */

public class CrashManager implements Thread.UncaughtExceptionHandler {

    private final String TAG = "CrashManager";

    private final Context mContext;
    private final String mVersionCode;
    private final String mVersionName;
    private final Thread.UncaughtExceptionHandler mDefaultHandler;

    public CrashManager(Context context, String versionCode, String versionName) {
        mContext = context;
        mVersionCode = versionCode;
        mVersionName = versionName;
        //获取系统默认的UncaughtExceptionHandler
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
    }

    @Override
    public void uncaughtException(@NonNull Thread t, @NonNull Throwable e) {
        //异常为空
        if (null == e) {
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(0);
            return;
        }

        //获取异常信息
        Date now = new Date(System.currentTimeMillis());
        String applicationName = getApplicationName(mContext);
        String fileName = new SimpleDateFormat("yyyy-MM-dd HH-mm-ss", Locale.getDefault()).format(now) + ".txt";
        String filePath = new File(mContext.getExternalCacheDir(), "crash").getAbsolutePath() + File.separator;
        String finalPath = filePath + fileName;
        File file = createFileByPath(finalPath);
        if (null == file) return;
        new Thread(() -> {
            try (PrintWriter pw = new PrintWriter(new FileWriter(finalPath, false))) {
                pw.write(getCashHead());
                e.printStackTrace(pw);
                Throwable cause = e.getCause();
                while (cause != null) {
                    cause.printStackTrace(pw);
                    cause = cause.getCause();
                }
                // 输出异常到本地文件
                Logcat.obtain(TAG).e(Log.getStackTraceString(e));
            } catch (IOException e1) {
                e1.printStackTrace();
            }
        }).start();


        if (mDefaultHandler != null) {
            mDefaultHandler.uncaughtException(t, e);
        }

        Log.d(TAG, "uncaughtException...");
    }

    /**
     * 获取闪退头部信息
     */

    private String getCashHead() {
        Log.d(TAG, "获取闪退头部信息 mVersionName:" + mVersionName);
        Log.d(TAG, "获取闪退头部信息 mVersionCode:" + mVersionCode);

        String time = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(new Date());
        return "\n************* Crash Log Head ****************" +
                "\nDevice Manufacturer: " + Build.MANUFACTURER +// 设备厂商
                "\nDevice Model       : " + Build.MODEL +// 设备型号
                "\nAndroid Version    : " + Build.VERSION.RELEASE +// 系统版本
                "\nAndroid SDK        : " + Build.VERSION.SDK_INT +// SDK版本
                "\nApp VersionName    : " + mVersionName +//APP版本名称
                "\nApp VersionCode    : " + mVersionCode +//APP版本号
                "\nCaseTime     : " + time +//闪退时间
                "\n************* Crash Log Head ****************\n\n";
    }


    public static String getApplicationName(Context context) {
        String applicationName = "ApplicationName";

        if (null != context) {
            try {
                PackageManager packageManager = context.getPackageManager();
                PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);
                int labelRes = packageInfo.applicationInfo.labelRes;
                applicationName = context.getResources().getString(labelRes);
            } catch (PackageManager.NameNotFoundException e) {
                e.printStackTrace();
            }
        }

        return applicationName;
    }


    public static File createFileByPath(String path) {
        if (TextUtils.isEmpty(path)) return null;
        File file = new File(path);
        File parentFile = file.getParentFile();

        if (!parentFile.exists()) {
            parentFile.mkdirs();
        }

        try {
            file.createNewFile();
        } catch (IOException e) {
            return null;
        }

        return file;
    }
}
